package opengles;

import android.opengl.GLES20;
import android.opengl.GLES30;
import android.util.Log;

import java.nio.IntBuffer;
import java.util.ArrayList;

/**
 * Created by freehyan on 9/7/2016.
 */
public class FBO {
    private int[] mFBOId;
    private int[] mFBODepthBuf;
 //   private int[] mFBOTextureId;
    private ArrayList<Integer> mFBOTextureIds;
    private int mFBOWidth;
    private int mFBOHeight;

    public FBO() {
    }

    public void initFBO(int width, int height) {
        mFBOWidth = width;
        mFBOHeight = height;

        mFBOId = new int[1];
        mFBOTextureIds = new ArrayList<Integer>();
       // mFBOTextureId = new int[1];
       // createTexture(mFBOTextureId, width, height);

        GLES20.glGenFramebuffers(1, mFBOId, 0);
        GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFBOId[0]);

//        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mFBOTextureId[0]);
//        GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D,
//                mFBOTextureId[0], 0);

        mFBODepthBuf = new int[1];
        GLES20.glGenRenderbuffers(1, mFBODepthBuf, 0);
        GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, mFBODepthBuf[0]);
        GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER, GLES20.GL_DEPTH_COMPONENT16, width, height);
        GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_DEPTH_ATTACHMENT, GLES20.GL_RENDERBUFFER,
                mFBODepthBuf[0]);

        GLES20.glBindBuffer(GLES20.GL_RENDERBUFFER, 0);
  //      GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
        GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);

        if ( GLES20.glGetError() != GLES20.GL_NO_ERROR)
            Log.e("FBO","initFBO - rbo");

        if(GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER) != GLES20.GL_FRAMEBUFFER_COMPLETE)
            Log.e("FBO", "initFBO");
    }

    public void mountTexture(int[] texId, int mountId){
        createTexture(texId, mFBOWidth, mFBOHeight);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texId[0]);
        mFBOTextureIds.add(Integer.valueOf(texId[0]));
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
    }

    private void createTexture(int[] textureId, int width, int height) {
        GLES20.glGenTextures(1, textureId, 0);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId[0]);
        GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width, height, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
    }

    public void attachTex2FBO(){
        GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFBOId[0]);
        if(GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER) != GLES20.GL_FRAMEBUFFER_COMPLETE)
            Log.e("FBO", "FBO Imcomplete");

        int Size = mFBOTextureIds.size();
        int[] ColorBuffers = new int[Size];
        for (int i=0; i<Size; i++)
        {
            int TempTextureId = mFBOTextureIds.get(i).intValue();
            GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0 + i, GLES20.GL_TEXTURE_2D,
                    TempTextureId, 0);
            ColorBuffers[i] = GLES20.GL_COLOR_ATTACHMENT0 + i;
        }
        IntBuffer intBuffer = IntBuffer.wrap(ColorBuffers);
        GLES30.glDrawBuffers(Size, intBuffer);
        GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
    }

    public void bindForReadTargetTex(int textureUnit, int textureId){
        GLES20.glActiveTexture(textureUnit);
        GLES20.glEnable(GLES20.GL_TEXTURE_2D);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);
    }

    public void openFBO(){
        GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFBOId[0]);
    }

    public void closeFBO(){
        GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
    }

    public void destroyResours(){
        GLES20.glDeleteRenderbuffers(1, mFBODepthBuf, 0);
        GLES20.glDeleteFramebuffers(1, mFBOId, 0);
        for (int i=0; i<mFBOTextureIds.size(); i++) {
            int[] FBOTextureId = new int[1];
            FBOTextureId[0] = mFBOTextureIds.get(i).intValue();
            GLES20.glDeleteTextures(1, FBOTextureId, 0);
        }
    }
}
